#!/usr/bin/env python3
# Before run this script, Run 'pip download -r requirment.txt' to make sure all depended module exists
#   Run 'pip freeze' to output requirment.txt
import sys
import os
import pwd
import stat
import platform
import getpass
import tarfile

### platform constant
platform_tags = ["MacOS_i386" "Linux_x86_64" "Linux_aarch64"]
macos_i386 = 0
linux_x86 = 1
linux_aarch64 = 2

### environment constant
key_standalone_sdk_profile = "STANDALONE_SDK_PROFILE_PATH"

# argv[1]: online/offline
print(sys.argv)
is_online = False

# check file attributes
def is_readable(path, user):
    user_info = pwd.getpwnam(user)
    uid = user_info.pw_uid
    gid = user_info.pw_gid
    s = os.stat(path)
    mode = s[stat.ST_MODE]
    return (((s[stat.ST_UID] == uid) and (mode & stat.S_IRUSR > 0)) or ((s[stat.ST_GID] == gid) and (mode & stat.S_IRGRP > 0)) or (mode & stat.S_IROTH > 0))

def is_writable(path, user):
    user_info = pwd.getpwnam(user)
    uid = user_info.pw_uid
    gid = user_info.pw_gid
    s = os.stat(path)
    mode = s[stat.ST_MODE]
    return (((s[stat.ST_UID] == uid) and (mode & stat.S_IWUSR > 0)) or((s[stat.ST_GID] == gid) and (mode & stat.S_IWGRP > 0)) or (mode & stat.S_IWOTH > 0))

def is_executable(path, user):
    user_info = pwd.getpwnam(user)
    uid = user_info.pw_uid
    gid = user_info.pw_gid
    s = os.stat(path)
    mode = s[stat.ST_MODE]
    return (((s[stat.ST_UID] == uid) and (mode & stat.S_IXUSR > 0)) or ((s[stat.ST_GID] == gid) and (mode & stat.S_IXGRP > 0)) or (mode & stat.S_IXOTH > 0))

def un_tar(src_path, dst_dir):
    tar = tarfile.open(name=src_path)

    for member_info in tar.getmembers():
        print("- extracting: " + member_info.name)
        tar.extract(member=member_info, path=dst_dir)

    tar.close()

#################################################################
# STEP 1: Check environment
# check if it is offline install or online install
for i in range(1, len(sys.argv)):
    if('-online' == sys.argv[i]) or ('-on' == sys.argv[i]) or ('-o' == sys.argv[i]):
        is_online = True

print("[1]: Online install" if is_online else "[1]: Offline install")

# check install environment
install_platform = -1

# check cpu arch and os system for CC
if (platform.system() == 'Darwin' ) and (platform.processor() == 'i386'):
    install_platform = macos_i386
elif (platform.system() == 'Linux' ) and (platform.processor() == 'x86_64'):
    install_platform = linux_x86
elif (platform.system() == 'Linux' ) and (platform.processor() == 'aarch64'):
    install_platform = linux_aarch64
else:
    print("[1]: Platform not Support !!! ")
    exit()

# get current user to install, profile depends on user
usr = getpass.getuser()
print("[1]: Usr: {}, OS: {}, Arch: {}, Type: {}".format(usr, platform.system(), platform.processor(), install_platform))

# check environment variables
if (install_platform == macos_i386):
    os.environ.setdefault(key_standalone_sdk_profile, '.bash_profile')
else:
    os.environ.setdefault(key_standalone_sdk_profile, ".profile")

# get absolute path of profile 
profile_path = os.environ.get('HOME') + '/' + os.environ.get(key_standalone_sdk_profile)
active_envir_msg = "source {}".format(profile_path)

# make sure profile is accessable for the user
if not is_readable(profile_path, usr) or \
   not is_writable(profile_path, usr) or \
   not is_executable(profile_path, usr):
    print("[1]: Profile '{}' not exist or non access rights !!!".format(profile_path))
    exit()

print("[1]: Enviroment Variables will set at {}".format(profile_path))

# get absoulte path current pwd to install sdk
install_path, install_script = os.path.split(os.path.abspath(__file__))
curr_path = os.getcwd()
standalone_sdk_path = ''

# in case user call this script not from current path
if (curr_path != install_path):
    print("[1]: Please cd to install script path first !!!")
    exit()

# get absolute path of sdk install dir
standalone_sdk_path = install_path
print("[1]: Standalone SDK at {}".format(standalone_sdk_path))

# make sure sdk scripts are executable
if ( install_platform == macos_i386 ):
    os.system("chmod +x ./*.sh ")
    os.system("chmod +x ./scripts/*.sh ")
    os.system("chmod +x ./make/*.mk ")
    os.system("chmod +x ./lib/Kconfiglib/*.py ")
else:
    os.system("chmod +x ./*.sh --silent ")
    os.system("chmod +x ./scripts/*.sh --silent ")
    os.system("chmod +x ./make/*.mk --silent ")
    os.system("chmod +x ./lib/Kconfiglib/*.py --silent ")

## STEP 2: reset environment
# remove environment variables, freeBSD and MacOS require backup before edit
if ( install_platform == macos_i386 ):
    os.system("sed -i \".bak\" '/### PHYTIUM STANDALONE SDK SETTING START/d' " + profile_path)
    os.system("sed -i \".bak\" '/export AARCH32_CROSS_PATH=/d' " + profile_path)
    os.system("sed -i \".bak\" '/export PATH=\$PATH:\$AARCH32_CROSS_PATH/d' " + profile_path)
    os.system("sed -i \".bak\" '/export AARCH64_CROSS_PATH=/d' " + profile_path)
    os.system("sed -i \".bak\" '/export PATH=\$PATH:\$AARCH64_CROSS_PATH/d' " + profile_path)
    os.system("sed -i \".bak\" '/export STANDALONE_SDK_ROOT=/d' " + profile_path)
    os.system("sed -i \".bak\" '/### PHYTIUM STANDALONE SDK SETTING END/d' "+ profile_path)
else:
    os.system("sed -i '/### PHYTIUM STANDALONE SDK SETTING START/d' "+ profile_path)
    os.system("sed -i '/export AARCH32_CROSS_PATH=/d' " + profile_path)
    os.system("sed -i '/export PATH=\$PATH:\$AARCH32_CROSS_PATH/d' " + profile_path)
    os.system("sed -i '/export AARCH64_CROSS_PATH=/d' " + profile_path)
    os.system("sed -i '/export PATH=\$PATH:\$AARCH64_CROSS_PATH/d' " + profile_path)
    os.system("sed -i '/export STANDALONE_SDK_ROOT=/d' " + profile_path)
    os.system("sed -i '/### PHYTIUM STANDALONE SDK SETTING END/d' "+ profile_path)

print("[2]: Reset Environment")

## STEP 3: install cross-platform compiler
cc_install_path = standalone_sdk_path + '/' + 'tools' + '/'

# set cc package name, download url and install dst dir
if (install_platform == macos_i386):
    # name of cc package, also name od install dir
    aarch32_cc = 'gcc-arm-none-eabi-10.3-2021.07-mac-10.14.6'
    aarch64_cc = 'gcc-arm-none-eabi-10.3-2021.07-mac-10.14.6' # not found aarch64 cc for MacOS

    # + suffix = cc package name
    aarch32_cc_pack = aarch32_cc + '.tar.bz2'
    aarch64_cc_pack = aarch64_cc + '.tar.bz2'  

    # cc package url for online install
    # aarch32_cc_url = 'https://gitee.com/phytium_embedded/phytium-standalone-sdk/attach_files/776847/download/gcc-arm-x86_64-none-eabi-10-2020-q4-major.tar.xz'
    # aarch64_cc_url = 'https://gitee.com/phytium_embedded/phytium-standalone-sdk/attach_files/776846/download/gcc-arm-x86_64-aarch64-none-elf-10.2-2020.11.tar.xz'

    # full path of install dst dir
    aarch32_cc_install_path = cc_install_path + aarch32_cc
    aarch64_cc_install_path = cc_install_path + aarch64_cc

elif (install_platform == linux_x86):
    aarch32_cc = 'gcc-arm-x86_64-none-eabi-10-2020-q4-major'
    aarch64_cc = 'gcc-arm-x86_64-aarch64-none-elf-10.2-2020.11'

    # cc package name
    aarch32_cc_pack = aarch32_cc + '.tar.xz'
    aarch64_cc_pack = aarch64_cc + '.tar.xz' 

    aarch32_cc_url = 'https://gitee.com/phytium_embedded/phytium-standalone-sdk/attach_files/776847/download/gcc-arm-x86_64-none-eabi-10-2020-q4-major.tar.xz'
    aarch64_cc_url = 'https://gitee.com/phytium_embedded/phytium-standalone-sdk/attach_files/776846/download/gcc-arm-x86_64-aarch64-none-elf-10.2-2020.11.tar.xz'

    aarch32_cc_install_path = cc_install_path + aarch32_cc
    aarch64_cc_install_path = cc_install_path + aarch64_cc
elif (install_platform == linux_aarch64):

    aarch32_cc = 'gcc-arm-aarch64-none-eabi-10-2020-q4-major'
    aarch64_cc = 'gcc-arm-10.2-2020.11-aarch64-aarch64-none-elf'

    # cc package name
    aarch32_cc_pack = aarch32_cc + '.tar.xz'
    aarch64_cc_pack = aarch64_cc + '.tar.xz' 

    aarch32_cc_url = 'https://gitee.com/phytium_embedded/phytium-standalone-sdk/attach_files/779742/download/gcc-arm-aarch64-none-eabi-10-2020-q4-major.tar.xz'
    aarch64_cc_url = 'https://gitee.com/phytium_embedded/phytium-standalone-sdk/attach_files/779743/download/gcc-arm-10.2-2020.11-aarch64-aarch64-none-elf.tar.xz'

    aarch32_cc_install_path = cc_install_path + aarch32_cc
    aarch64_cc_install_path = cc_install_path + aarch64_cc

print("[3]: Download and Install CC....")

# check if cc has already been installed
aarch32_cc_is_installed = os.path.exists(aarch32_cc_install_path)
aarch64_cc_is_installed = os.path.exists(aarch64_cc_install_path)

# cc download target
aarch32_cc_dl_dst = cc_install_path + aarch32_cc_pack
aarch64_cc_dl_dst = cc_install_path + aarch64_cc_pack

if is_online: #online
    import wget

    # download aarch32 cc package
    if not aarch32_cc_is_installed:
        print("[3] Download AARCH32 CC from {}...".format(aarch32_cc_url))
        cc_file = wget.download(aarch32_cc_url, aarch32_cc_dl_dst)
        if not os.path.exists(cc_file) or not (cc_file == aarch32_cc_dl_dst):
            print("[3]: Download AARCH32 CC Failed!!!")
            exit()
        else:
            print("[3]: Download AARCH32 CC at {}".format(aarch32_cc_dl_dst))

    # download aarch64 cc package
    if not aarch64_cc_is_installed:
        print("[3] Download AARCH64 CC from {}...".format(aarch64_cc_url))
        cc_file = wget.download(aarch64_cc_url, aarch64_cc_dl_dst)    
        if not os.path.exists(cc_file) or not (cc_file == aarch64_cc_dl_dst):
            print("[3]: Download AARCH64 CC Failed!!!")
            exit()
        else:
            print("[3]: Download AARCH64 CC at {}".format(aarch64_cc_dl_dst))

else: #offline, assert cc package exists
    if not os.path.exists(aarch32_cc_dl_dst):
        print("[3]: Failed, AARCH32 CC Package {} Non Found !!!".format(aarch32_cc_dl_dst))
        exit()

    if not os.path.exists(aarch64_cc_dl_dst):
        print("[3]: Failed, AARCH64 CC Package {} Non Found !!!".format(aarch64_cc_dl_dst))
        exit()

# untar aarch32 cc
if not aarch32_cc_is_installed:
    if os.path.exists(aarch32_cc_dl_dst):
        print("[3]: Install AARCH32 CC...")
        un_tar(aarch32_cc_dl_dst, cc_install_path)

# write aarch32 cc path
if os.path.exists(aarch32_cc_install_path):
    print("[3]: AARCH32 CC Install Success at {}".format(aarch32_cc_install_path))
else:
    print("[3]: AARCH32 CC Install Failed !!!")
    exit()

# untar aarch64 cc
if not aarch64_cc_is_installed:
    if os.path.exists(aarch64_cc_dl_dst):
        print("[3]: Install AARCH64 CC...")
        un_tar(aarch64_cc_dl_dst, cc_install_path)

# write aarch64 cc path
if os.path.exists(aarch64_cc_install_path):
    print("[3]: AARCH64 CC Install Success at {}".format(aarch64_cc_install_path))
else:
    print("[3]: AARCH64 CC Install Failed !!!")
    exit()

## STEP 4: write environment variables
os.system("echo \"### PHYTIUM STANDALONE SDK SETTING START\" >> {}".format(profile_path))
os.system("echo \"export AARCH32_CROSS_PATH={}\" >> {}".format(aarch32_cc_install_path, profile_path))
os.system("echo \"export PATH=\$PATH:\$AARCH32_CROSS_PATH/bin\">> {}".format(profile_path))
os.system("echo \"export AARCH64_CROSS_PATH={}\" >> {}".format(aarch64_cc_install_path, profile_path))
os.system("echo \"export PATH=\$PATH:\$AARCH64_CROSS_PATH/bin\">> {}".format(profile_path))
os.system("echo \"export STANDALONE_SDK_ROOT={}\" >> {}".format(standalone_sdk_path, profile_path))
os.system("echo \"### PHYTIUM STANDALONE SDK SETTING END\" >> {}".format(profile_path))

## STEP 5: display success message and enable environment
print("[5]: Success!!! Standalone SDK is Install at {}".format(standalone_sdk_path))
print("[5]: Phytium Standalone SDK Setup Done for {}!!!".format(usr))
print("[6]: Run '{}' or Reboot System to Make it Active".format(active_envir_msg))